package lastmpd.lastfmAlbumCache;

/*
 * Copyright (C) 2010 Mark Breddemann
 * 
 * This program is free software; you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software Foundation;
 * either version 3 of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along with this
 * program; if not, see <http://www.gnu.org/licenses/>.
 */

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Properties;

import net.roarsoftware.lastfm.Album;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import lastmpd.LastfmConnection;
import lastmpd.LastfmSong;

public class LastfmAlbumCache {
	
	private final Log log = LogFactory.getLog(this.getClass());
	private HashMap<String, Artist> artists;
	private final LastfmConnection lastfmConnection;
	private final String cachefile;
	
	public LastfmAlbumCache(Properties properties, LastfmConnection lastfmConnection) {
		this.lastfmConnection = lastfmConnection;
		cachefile = properties.getProperty("lastfm.albumcache.cachefile");
		try {
			log.debug("loading album cache from file " + cachefile);
			ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(new FileInputStream(cachefile)));
			artists = (HashMap<String, Artist>) in.readObject();
			in.close();
			log.trace("album cache loaded");
			
		} catch (FileNotFoundException e) {
			log.warn("unable to load album cache. creating new");
			artists = new HashMap<String, Artist>();
			save();
		} catch (IOException e) {
			log.error("IOException while loading album cache: " + e.getMessage());
			log.warn("creating new album cache");
			artists = new HashMap<String, Artist>();
			save();
		} catch (ClassNotFoundException e) {
			log.error("ClassNotFoundException while loading album cache: " + e.getMessage());
			log.warn("creating new album cache");
			artists = new HashMap<String, Artist>();
			save();
		}
	}
	
	public void fillAlbumNames(ArrayList<LastfmSong> songList) {
		
		for (LastfmSong song: songList) {
			String artist = song.getArtist();
			if (!artists.containsKey(artist)) {
				log.info("no album info for " + artist);
				getAlbumInfo(artist);
			}
			if (!artists.containsKey(artist)) {
				log.warn("again no album info! skipping " + song.getArtist() + " - " + song.getSong());
			} else {
				
				
				for (lastmpd.lastfmAlbumCache.Album cacheAlbum: artists.get(artist).getAlbums()) {
					if (cacheAlbum.getTracks().contains(song.getSong())) {
						log.trace("album name for " + song.getArtist() + " - " + song.getSong() + ": " + cacheAlbum.getAlbumName());
						song.setAlbum(cacheAlbum.getAlbumName());
						break;
					}
				}
			}
		}
		
	}
	
	private void getAlbumInfo(String artist) {
		log.info("fetching album info for " + artist);
		
		ArrayList<lastmpd.lastfmAlbumCache.Album> cacheAlbums = new ArrayList<lastmpd.lastfmAlbumCache.Album>();
		Artist cacheArtist= new Artist(cacheAlbums);
		
		ArrayList<Album> fmAlbums = lastfmConnection.getTopAlbumsFromArtist(artist, 20);
		
		for (Album album: fmAlbums) {
			log.info("fetching album info: " + album.getName());
			
			ArrayList<String> fmSongs = lastfmConnection.getSongsFromAlbum(album);
			if (fmSongs != null) {
				
				log.debug("got " + fmSongs.size() + " tracks for this album");
				
				lastmpd.lastfmAlbumCache.Album cacheAlbum = new lastmpd.lastfmAlbumCache.Album(fmSongs, album.getName());
				cacheAlbums.add(cacheAlbum);
				
			}
			
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		artists.put(artist, cacheArtist);
		
		save();
		log.debug("fetched album infos for " + artist);
	}
	
	private void save() {
		log.debug("saving album cache");
		try {
			ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(cachefile)));
			out.writeObject(artists);
			out.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
